package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.constant.PublishConstants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.OrderStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bo.POrderBo;
import com.ruoyi.system.domain.vo.POrderVo;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IPOrderService;
import com.ruoyi.system.service.IPUserBrokerageRecordService;
import com.ruoyi.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 咨询订单Service业务层处理
 *
 * @author ruoyi
 * @date 2022-07-25
 */
@RequiredArgsConstructor
@Service
public class POrderServiceImpl implements IPOrderService {

    private final POrderMapper baseMapper;
    private final ISysUserService userService;
    private final SysUserMapper sysUserMapper;
    private final IPUserBrokerageRecordService brokerageRecordService;
    private final PSystemConfigMapper configMapper;
    private final PAskCouponMapper askCouponMapper;
    private final PQuestionTopicMapper topicMapper;
    private final SysDictDataMapper sysDictDataMapper;
    private final PMessageMapper pMessageMapper;
    private final PUserLevelMapper pUserLevelMapper;

    /**
     * 查询咨询订单
     */
    @Override
    public POrder queryById(Long id){
        return baseMapper.selectMyById(id);
    }

    /**
     * 查询咨询订单列表
     */
    @Override
    public TableDataInfo<POrder> queryPageList(POrder bo, PageQuery pageQuery) {
        QueryWrapper<POrder> lqw = Wrappers.query();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), "o.title", bo.getTitle());
        lqw.like(StringUtils.isNotBlank(bo.getUsername()), "u.user_name", bo.getUsername());
        lqw.like(StringUtils.isNotBlank(bo.getAdviserName()), "s.user_name", bo.getAdviserName());
        lqw.eq(StringUtils.isNotBlank(bo.getServiceType()), "o.service_type", bo.getServiceType());
        lqw.eq(StringUtils.isNotBlank(bo.getIsCoupon()), "o.is_coupon", bo.getIsCoupon());
        lqw.eq(bo.getAskType() != null, "o.ask_type", bo.getAskType());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), "o.order_status", bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPayType()), "o.pay_type", bo.getPayType());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderCategory()), "o.order_category", bo.getOrderCategory());
        lqw.eq(ObjectUtil.isNotEmpty(bo.getAdviserId()), "o.adviser_id", bo.getAdviserId());
        lqw.eq(ObjectUtil.isNotEmpty(bo.getUserId()), "o.user_id", bo.getUserId());
        Page<POrder> result = baseMapper.selectMyLeftPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询咨询订单列表
     */
    @Override
    public List<POrderVo> queryList(POrderBo bo) {
        LambdaQueryWrapper<POrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<POrder> buildQueryWrapper(POrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<POrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), POrder::getTitle, bo.getTitle());
        lqw.eq(bo.getUserId() != null, POrder::getUserId, bo.getUserId());
        lqw.eq(bo.getAdviserId() != null, POrder::getAdviserId, bo.getAdviserId());
        lqw.eq(StringUtils.isNotBlank(bo.getServiceType()), POrder::getServiceType, bo.getServiceType());
        lqw.eq(StringUtils.isNotBlank(bo.getIsCoupon()), POrder::getIsCoupon, bo.getIsCoupon());
        lqw.eq(bo.getStartTime() != null, POrder::getStartTime, bo.getStartTime());
        lqw.eq(StringUtils.isNotBlank(bo.getTimeSize()), POrder::getTimeSize, bo.getTimeSize());
        lqw.eq(bo.getAskType() != null, POrder::getAskType, bo.getAskType());
        lqw.eq(bo.getAppointmentTime() != null, POrder::getAppointmentTime, bo.getAppointmentTime());
        lqw.eq(bo.getPrice() != null, POrder::getPrice, bo.getPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderStatus()), POrder::getOrderStatus, bo.getOrderStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getPayType()), POrder::getPayType, bo.getPayType());
        lqw.eq(StringUtils.isNotBlank(bo.getReturnRemark()), POrder::getReturnRemark, bo.getReturnRemark());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderCategory()), POrder::getOrderCategory, bo.getOrderCategory());
        return lqw;
    }

    /**
     * 新增咨询订单
     */
    @Override
    public Boolean insertByBo(POrderBo bo) {
        POrder add = BeanUtil.toBean(bo, POrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改咨询订单
     */
    @Override
    public Boolean updateByBo(POrderBo bo) {
        POrder update = BeanUtil.toBean(bo, POrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(POrder entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除咨询订单
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertFontByBo(POrderBo bo) {
        POrder add = BeanUtil.toBean(bo, POrder.class);
        Long userId = LoginHelper.getUserId();
        // 初始化参数
        add.setUserId(userId);
        Long couponId = bo.getCouponId();
        if (ObjectUtil.isNotEmpty(couponId)) {
            PAskCoupon coupon = askCouponMapper.selectById(couponId);
            if (ObjectUtil.isEmpty(coupon)) {
                throw new ServiceException("非法购物券！");
            }


        }

        // 待付款
        add.setOrderStatus(OrderStatus.UN_PAY.getValue());
        //String orderNo = CharUtil.getRandomNum(16);
        add.setOrderNo(bo.getOrderNo());
        add.setOrderCategory(PublishConstants.COMMON_YES);

        Date nows = new Date();
        //当前时间
        if(!"2".equals(add.getServiceType()) && !"1".equals(add.getServiceType())){
            int hmiao = Integer.parseInt(add.getTimeSize()) * 60000;
            Date afterDate = new Date(nows .getTime() + hmiao);
            add.setAppointmentTime(afterDate);
        }
        if ("0".equals(add.getServiceType()) || "2".equals(add.getServiceType())) {
            RedisUtils.setCacheObject(PublishConstants.TIMING_KEY + bo.getOrderNo(),bo.getOrderCategory(), Duration.ofMinutes(Long.parseLong(bo.getTimeSize())));
        }

        add.setStartTime(nows);
        baseMapper.insert(add);
        Date appointmentTime = add.getAppointmentTime();
        // 如果有预约时间，存入key,到缓存中
        if (ObjectUtil.isNotEmpty(appointmentTime)) {
            Date now = new Date();
            long waitMinutes = DateUtils.differentMinutesByMillisecond(now, appointmentTime);
            String key = PublishConstants.ASK_ORDER_KEY + add.getId();
            RedisUtils.setCacheObject(key, add.getId(), Duration.ofMinutes(waitMinutes));
        }
    }




    @Override
    public void editStatus(POrder bo) {
        if (ObjectUtil.isEmpty(bo) || ObjectUtil.isEmpty(bo.getId())) {
            throw new ServiceException("非法参数！");
        }

        String orderStatus = bo.getOrderStatus();
        if (StringUtils.isBlank(orderStatus)) {
            throw new ServiceException("订单状态不能为空！");
        }

        baseMapper.updateById(bo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void askPayOk(POrder bo) {
        if (ObjectUtil.isEmpty(bo) || ObjectUtil.isEmpty(bo.getId())) {
            throw new ServiceException("非法参数！");
        }

        String orderStatus = bo.getOrderStatus();
        if (StringUtils.isBlank(orderStatus)) {
            throw new ServiceException("订单状态不能为空！");
        }

        if (!OrderStatus.UN_PAY.getValue().equals(orderStatus)) {
            throw new ServiceException("非法订单！");
        }
        // 更新订单状态
        bo.setOrderStatus(OrderStatus.WAIT_ASK.getValue());
        baseMapper.updateById(bo);
        PMessage message = new PMessage();
        message.setSecondType("1")
            .setCreateUserId(bo.getUserId())
            .setToUserId(bo.getAdviserId())
            .setStatus("0");
        this.pMessageMapper.insert(message);
        // 支付成功后分销
        Long userId = bo.getUserId();
        if (ObjectUtil.isEmpty(userId)) {
            throw new ServiceException("用户参数不能为空！");
        }

        BigDecimal actualPrice = bo.getActualPrice();
        SysUser sysUser = userService.selectFrontById(userId);
        // 设置分销
        setTheCommission(sysUser, actualPrice, Long.parseLong(bo.getOrderNo()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void testPayOk(POrder bo) {
        if (ObjectUtil.isEmpty(bo) || ObjectUtil.isEmpty(bo.getId())) {
            throw new ServiceException("非法参数！");
        }

        String orderStatus = bo.getOrderStatus();
        if (StringUtils.isBlank(orderStatus)) {
            throw new ServiceException("非法订单状态！");
        }

        if (!OrderStatus.UN_PAY.getValue().equals(orderStatus)) {
            throw new ServiceException("非法订单！");
        }
        // 更新订单状态
        bo.setOrderStatus(OrderStatus.WAIT_ASK.getValue());

        // 用户消费升级
        this.upgrade(bo.getUserId(), bo.getActualPrice());

        baseMapper.updateById(bo);
        // 支付成功后修改题目测试人数
        Long topicId = bo.getTopicId();
        if (ObjectUtil.isEmpty(topicId)) {
            throw new ServiceException("测试题目不能为空！");
        }

        PQuestionTopic questionTopic = topicMapper.selectById(topicId);
        if (ObjectUtil.isEmpty(questionTopic)) {
            throw new ServiceException("非法题目！");
        }

        questionTopic.setPersonNum(questionTopic.getPersonNum() + 1);
        topicMapper.updateById(questionTopic);
        // 支付成功后分销
        Long userId = bo.getUserId();
        if (ObjectUtil.isEmpty(userId)) {
            throw new ServiceException("用户参数不能为空！");
        }

        BigDecimal actualPrice = bo.getActualPrice();
        SysUser sysUser = userService.selectUserById(userId);
        // 设置分销
        setTheCommission(sysUser, actualPrice, Long.parseLong(bo.getOrderNo()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrder(POrder bo) {
        if (ObjectUtil.isEmpty(bo) || ObjectUtil.isEmpty(bo.getId())) {
            throw new ServiceException("非法参数！");
        }

        String orderStatus = bo.getOrderStatus();
        if (StringUtils.isBlank(orderStatus)) {
            throw new ServiceException("订单状态不能为空！");
        }

        if (OrderStatus.WAIT_ADVISER.getValue().equals(orderStatus)) {
            throw new ServiceException("开始咨询后不可取消订单！");
        }

        bo.setOrderStatus(OrderStatus.CANCEL.getValue());

        baseMapper.updateById(bo);
        // 退款TODO
    }

    @Override
    public TableDataInfo<POrder> queryHasTimePageList(POrder bo, PageQuery pageQuery) {
        QueryWrapper<POrder> lqw = Wrappers.query();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), "o.title", bo.getTitle());
        lqw.like(StringUtils.isNotBlank(bo.getUsername()), "u.user_name", bo.getUsername());
        lqw.like(StringUtils.isNotBlank(bo.getAdviserName()), "s.user_name", bo.getAdviserName());
        lqw.eq(StringUtils.isNotBlank(bo.getServiceType()), "o.service_type", bo.getServiceType());
        lqw.eq(StringUtils.isNotBlank(bo.getIsCoupon()), "o.is_coupon", bo.getIsCoupon());
        lqw.eq(bo.getAskType() != null, "o.ask_type", bo.getAskType());
        lqw.notIn(StringUtils.isNotBlank(bo.getOrderStatus()), "o.order_status", OrderStatus.FINISH.getValue(), OrderStatus.CANCEL.getValue());
        lqw.eq(StringUtils.isNotBlank(bo.getPayType()), "o.pay_type", bo.getPayType());
        lqw.eq(StringUtils.isNotBlank(bo.getOrderCategory()), "o.order_category", bo.getOrderCategory());
        lqw.eq(ObjectUtil.isNotEmpty(bo.getAdviserId()), "o.adviser_id", bo.getAdviserId());
        lqw.eq(ObjectUtil.isNotEmpty(bo.getUserId()), "o.user_id", bo.getUserId());
        Page<POrder> result = baseMapper.selectMyLeftPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<POrder> list(String orderStatus, PageQuery pageQuery) {
        pageQuery.setPageNum(pageQuery.getPageNum() * pageQuery.getPageSize());
        return TableDataInfo.build(this.baseMapper.listMyOrder(pageQuery, LoginHelper.getUserId(), orderStatus));
    }

    @Override
    public POrder orderDetail(String orderNo) {
        return this.baseMapper.selectByOrderNo(orderNo);
    }

    @Override
    public void insertTestFontByBo(POrderBo bo) {
        POrder add = BeanUtil.toBean(bo, POrder.class);
        Long userId = LoginHelper.getUserId();
        // 初始化参数
        add.setUserId(userId);
        Long couponId = bo.getCouponId();
        if (ObjectUtil.isNotEmpty(couponId)) {
            PAskCoupon coupon = askCouponMapper.selectById(couponId);
            if (ObjectUtil.isEmpty(coupon)) {
                throw new ServiceException("非法购物券！");
            }
        } else {
            add.setActualPrice(add.getPrice());
        }
        // 待付款
        add.setOrderStatus(OrderStatus.UN_PAY.getValue());
        //String orderNo = CharUtil.getRandomNum(16);
        add.setOrderNo(bo.getOrderNo());
        add.setOrderCategory(PublishConstants.COMMON_NO);
        baseMapper.insert(add);
    }

    @Override
    public POrder orderFontDetail(String orderNo) {
        return baseMapper.selectOne(new LambdaQueryWrapper<POrder>().eq(POrder::getOrderNo, orderNo));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccessCallback(POrderBo bo) {
        bo.setOrderStatus(OrderStatus.WAIT_ADVISER.getValue());
        this.updateByBo(bo);

        BigDecimal payPrice = bo.getActualPrice();


        SysDictData data = this.sysDictDataMapper.selectOne(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "sys_scale").eq(SysDictData::getDictLabel, "扣除比例"));

        // 按照比例扣除平台费
        BigDecimal deduct = new BigDecimal(data.getDictValue());

        // 咨询师
        SysUser consultant = this.sysUserMapper.selectUserFontById(bo.getAdviserId());
        consultant.setBalance(consultant.getBalance().add(payPrice.multiply(deduct.multiply(new BigDecimal("100")))));
        this.userService.updateUser(consultant);

        this.upgrade(bo.getUserId(), payPrice);

    }

    @Override
    public void upgrade(Long userId, BigDecimal bigDecimal) {
        SysUser sysUser = this.sysUserMapper.selectUserFontById(userId);
        Integer userExperience = sysUser.getExperience();
        if (userExperience == null) {
            userExperience = 0;
        }

        // 用户经验
        int experience = bigDecimal.add(new BigDecimal(userExperience)).intValue();

        PUserLevel userLevel = this.pUserLevelMapper.selectById(sysUser.getMemberId());
        // 当前会员等级等级
        long level = ObjectUtil.isNull(userLevel) ? 0 : userLevel.getGrade();

        List<PUserLevel> pUserLevels = this.pUserLevelMapper.selectList(new LambdaQueryWrapper<PUserLevel>());

        for (PUserLevel pUserLevel : pUserLevels) {
            if (experience > pUserLevel.getExperience() && level < pUserLevel.getGrade()) {
                level = pUserLevel.getGrade();
                sysUser.setMemberId(pUserLevel.getId().toString());
            }
        }
        sysUser.setExperience(experience);
        this.sysUserMapper.updateById(sysUser);
    }

    /**
     * 计算佣金（二级）
     */
    public void setTheCommission(SysUser user, BigDecimal balance, long orderId) {

        if (ObjectUtil.isNotEmpty(user)) {
            // 一级推广
            Long spreadIdLevle1 = user.getSpreadId();
            if (ObjectUtil.isNotEmpty(spreadIdLevle1)) {
                SysUser spreadUser = userService.selectFrontById(spreadIdLevle1);
                String type = "normal_user";
                if ("0".equals(spreadUser.getMemberId())) {
                    type = "gold_vip_one";
                } else if ("1".equals(spreadUser.getMemberId())) {
                    type = "platinum_vip_one";
                } else if ("2".equals(spreadUser.getMemberId())) {
                    type = "diamond_vip_one";
                }
                SysDictData data = this.sysDictDataMapper.selectOne(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "distribution_amount").eq(SysDictData::getDictLabel, type));
                BigDecimal firstMoney = balance.multiply(new BigDecimal(data.getDictValue()).divide(BigDecimal.valueOf(100)));
                spreadUser.setBalance(spreadUser.getBalance().add(firstMoney));
                userService.updateUser(spreadUser);
                // 生成佣金记录
                PUserBrokerageRecord record = new PUserBrokerageRecord();
                record.setOrderId(orderId);
                record.setUid(spreadIdLevle1);
                record.setTitle("一级佣金提成");
                record.setType("0");
                record.setPrice(firstMoney);
                record.setBrokerageLevel(1);
                brokerageRecordService.insertFront(record);
                // 二级推广
                Long spreadIdLevel2 = spreadUser.getSpreadId();
                if (ObjectUtil.isNotEmpty(spreadIdLevel2)) {
                    SysUser spreadUser2 = userService.selectFrontById(spreadIdLevel2);
                    if ("0".equals(spreadUser.getMemberId())) {
                        type = "gold_vip_two";
                    } else if ("1".equals(spreadUser.getMemberId())) {
                        type = "platinum_vip_two";
                    } else if ("2".equals(spreadUser.getMemberId())) {
                        type = "diamond_vip_two";
                    }
                    SysDictData data1 = this.sysDictDataMapper.selectOne(new LambdaQueryWrapper<SysDictData>().eq(SysDictData::getDictType, "distribution_amount").eq(SysDictData::getDictLabel, type));
                    BigDecimal secondMoney = balance.multiply(new BigDecimal(data1.getDictValue()).divide(BigDecimal.valueOf(100)));
                    spreadUser2.setBalance(spreadUser2.getBalance().add(secondMoney));
                    userService.updateUser(spreadUser2);
                    // 生成佣金记录
                    PUserBrokerageRecord record2 = new PUserBrokerageRecord();
                    record2.setOrderId(orderId);
                    record2.setUid(spreadIdLevel2);
                    record2.setTitle("二级佣金提成");
                    record2.setType("0");
                    record2.setPrice(secondMoney);
                    record2.setBrokerageLevel(2);
                    brokerageRecordService.insertFront(record2);
                }
            }
        }

    }
}
